package org.spider.spiderweb.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spider.api.annotation.Comment;
import org.spider.api.domain.model.SpiderFlow;
import org.spider.api.domain.utilDomain.Grammer;
import org.spider.api.domain.utilDomain.Result;
import org.spider.api.executor.FunctionExecutor;
import org.spider.api.executor.FunctionExtension;
import org.spider.api.expression.interfaces.Grammerable;
import org.spider.api.utils.MyDateUtil;
import org.spider.core.job.SpiderJob;
import org.spider.core.job.SpiderJobManager;
import org.spider.core.service.SpiderFlowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.util.*;

@RestController
@RequestMapping("/spider")
public class SpiderController {
    private static final Logger logger = LoggerFactory.getLogger(SpiderController.class);
    @Resource
    private SpiderFlowService spiderFlowService;
    @Resource
    private SpiderJobManager spiderJobManager;
    @Resource
    private SpiderJob spiderJob;
    private final List<FunctionExecutor> executorList;
    private final List<FunctionExtension> extensionList;
    private final List<Grammerable> grammerables;

    private final static List<Grammer> grammars = new ArrayList<>();
    private final static Map<String,List<Grammer>> grammarMap =new HashMap<>();
    private static String saveFileDirPath;

    @Autowired
    public SpiderController(List<FunctionExecutor> executorList, List<FunctionExtension> extensionList, List<Grammerable> grammerables) {
        this.executorList = executorList;
        this.extensionList = extensionList;
        this.grammerables = grammerables;
    }

    @Value("${spider.workplace}")
    private void initSaveFileDir(String workplace){
        File saveFileDir = new File(workplace,"file");
        saveFileDirPath = saveFileDir.getAbsolutePath();
    }

    private void grammarHelper(){
        for (FunctionExecutor executor : executorList) {
            String function = executor.getFunctionPrefix();
            //添加该执行器下的所有函数
            List<Grammer> functionGrammers = Grammer.findGrammers(executor.getClass(), function, function, true);
            Comment comment = executor.getClass().getAnnotation(Comment.class);
            Grammer grammer = new Grammer();
            if (comment != null)
                grammer.setComment(comment.value());
            grammer.setFunction(function);
            functionGrammers.add(grammer);
            grammars.addAll(functionGrammers);
            grammarMap.put(function,functionGrammers);
        }
        for (FunctionExtension extension : extensionList) {
            String owner = extension.support().getSimpleName();
            //添加扩展执行器的所有方法
            List<Grammer> extensionGrammers = Grammer.findGrammers(extension.getClass(), null, owner, true);
            grammars.addAll(extensionGrammers);
            grammarMap.put(owner,extensionGrammers);
        }
        for (Grammerable grammerable : grammerables) {
            List<Grammer> grammerables = grammerable.grammers(); //这个目前是response的解析方法
            Grammer grammer = grammerables.get(0);
            String owner = grammer.getOwner();
            if(grammarMap.containsKey(owner))
                grammarMap.get(owner).addAll(grammerables);
            else grammarMap.put(owner,grammerables);
        }
    }

    private void scanSchedulerHelper(){
        LambdaQueryWrapper<SpiderFlow> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(SpiderFlow::getCronEnable,"true");
        List<SpiderFlow> spiderFlows = spiderFlowService.list(wrapper);
        if(spiderFlows==null || spiderFlows.isEmpty())
            return;
        for(SpiderFlow spiderFlow:spiderFlows){
            if(StringUtils.isNotEmpty(spiderFlow.getCron())){
                Date date = spiderJobManager.addJob(spiderFlow);
                logger.info("流程:{} ,开始执行时间:{}",spiderFlow.getName(), MyDateUtil.format(date));
            }
        }
    }

    @PostConstruct
    private void init() {
        //生成语法帮助文档的数据
        grammarHelper();
        //扫描需要定时执行的任务
        scanSchedulerHelper();
    }

    @GetMapping("/grammer")
    public Result getGrammers() {
        return Result.getInstance(grammars);
    }
    @GetMapping("/grammerMap")
    public Result getGrammerMap(){
        return Result.getInstance(grammarMap);
    }

    //============================================flow运行状态控制==============================================

    @GetMapping("/run/{id}/{taskName}")
    public Result run(@PathVariable String id,@PathVariable String taskName) {
        spiderJob.runAsync(id,taskName);
        logger.info("run: {},{}",id,taskName);
        //返回文件目录
        return Result.getInstance(1,saveFileDirPath);
    }

    @GetMapping("/pause/{id}")
    public Result pause(@PathVariable String id) {
        return null;
    }

    @GetMapping("/stop/{id}")
    public Result stop(@PathVariable String id) {
        return null;
    }

    //============================================cron==============================================
    @GetMapping("/cron/executeTime")
    public Result getCronNextExecuteTime(@RequestParam("cron") String cron){
        return Result.getInstance(spiderFlowService.cronNextExecuteTime(cron,5));
    }
    @GetMapping("/startCron")
    public Result startCron(@RequestParam("id") String id){
        boolean started = spiderFlowService.startCron(id);
        return Result.getInstance(started);
    }

    @GetMapping("/stopCron")
    public Result stopCron(@RequestParam("id") String id){
        boolean stopped = spiderFlowService.stopCron(id);
        return Result.getInstance(stopped);
    }

    @GetMapping("/cron/update")
    public Result updateCron(@RequestParam("id")String id,
                             @RequestParam("cron") String cron){
        boolean updated = spiderFlowService.updateCron(id, cron);
        System.out.println("操作成功? "+updated);
        return Result.getInstance(updated);
    }

    //============================================test==============================================
    @GetMapping("/test")
    public Result test(){
        return Result.getInstance(1,saveFileDirPath);
    }


}

